/**
 * Title: Hyperbolic engine
 * Description: jFamilyTree Engine
 * Version: provider
 * Copyright: (c) 2001-2008
 * Terms of use:see license agreement at http://treebolic.sourceforge.net/en/license.htm
 * Author: Bernard Bou
 * Company: bsys
 * Update: Mon Mar 10 00:00:00 CEST 2008
 */
package jFamilyTree.core;

/**
 * Unit Circle mapping
 * 
 * @author Bernard Bou
 */
public class EuclidianLocation
{
	// D A T A
	/**
	 * Center in (Euclidian space) unit circle
	 */
	public final Complex center;

	/**
	 * Radius in (Euclidian space) unit circle
	 */
	public double radius;

	// C O N S T R U C T O R

	/**
	 * Construct location in euclidian
	 */
	public EuclidianLocation()
	{
		center = new Complex();
		radius = 0.;
	}

	// M A P . T O . U N I T  C I R C L E

	/**
	 * Map hyperspace to unit circle
	 */
	public void set(HyperLocation thisHyperLocation)
	{
		// euclidian radius
		radius = XMath.h2e(thisHyperLocation.radius);

		// distance to (0,0)
		if (thisHyperLocation.dist != 0.)
		{
			// map this euclidian circle C (center, eradius) to euclidian circle
			// C0 (origin, eradius)
			// z and zinv are the ends or diameter on (0,C) direction
			Complex z = new Complex(thisHyperLocation.center).multiply(radius / thisHyperLocation.dist);
			Complex zinv = new Complex(z).neg();

			// hyperbolic translation of this diameter
			HyperTranslation.map(z, thisHyperLocation.center);
			HyperTranslation.map(zinv, thisHyperLocation.center);

			// middle of mapped diameter
			z.add(zinv).multiply(0.5);

			// computed center
			center.set(z);
			radius = zinv.sub(z).mag();
		}
		else
		{
			// this is (0,0)
			center.set(thisHyperLocation.center);
		}
	}

	// E U C L I D I A N . D I S T A N C E

	/**
	 * Get Euclidian distance
	 * 
	 * @param z1
	 *        point
	 * @param z2
	 *        point
	 * @return Euclidian distance between z1 and z2
	 */
	static public double getDistance(Complex z1, Complex z2)
	{
		return Math.sqrt(square(z1.re - z2.re) + square(z1.im - z2.im));
	}

	/**
	 * Get squared Euclidian distance
	 * 
	 * @param z1
	 *        point
	 * @param z2
	 *        point
	 * @return squared Euclidian distance between z1 and z2
	 */
	static public double getDistanceSquare(Complex z1, Complex z2)
	{
		return square(z1.re - z2.re) + square(z1.im - z2.im);
	}

	/**
	 * Square (fast compute)
	 * 
	 * @param x
	 *        input
	 * @return square of x
	 */
	static private double square(double x)
	{
		return x * x;
	}

	// S T R I N G

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	public String toString()
	{
		return "eo=" + center + ", er=" + radius;
	}
}
